package com.ternnetwork.core.service.impl;


import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.persistence.LockModeType;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import com.ternnetwork.commons.model.http.BaseResponse;
import com.ternnetwork.commons.utils.DateUtils;
import com.ternnetwork.commons.utils.EncryptUtils;
import com.ternnetwork.commons.utils.ExcelUtils;
import com.ternnetwork.commons.utils.ExtendedStringUtils;
import com.ternnetwork.commons.utils.ValidateUtils;
import com.ternnetwork.persistence.page.BootstrapGrid;
import com.ternnetwork.persistence.page.Page;
import com.ternnetwork.core.dao.UserDao;
import com.ternnetwork.core.dao.org.OrganizationUserRelationshipDao;
import com.ternnetwork.core.entity.Role;
import com.ternnetwork.core.entity.User;
import com.ternnetwork.core.entity.org.Department;
import com.ternnetwork.core.enums.Gender;

import com.ternnetwork.core.service.RoleService;
import com.ternnetwork.core.service.UserRoleService;
import com.ternnetwork.core.service.UserService;
import com.ternnetwork.core.service.log.UserPasswordResetLogService;
import com.ternnetwork.core.service.org.DepartmentService;





@Service("userService")
public class UserServiceImpl implements UserService {
	private static final Logger log = Logger.getLogger(UserServiceImpl.class);

	
	@Resource
	private UserDao userDao;
	
	@Resource
	private UserRoleService userRoleService;
	
	@Resource
	private RoleService roleService;
	
	@Resource
	private DepartmentService departmentService;
	
	@Resource
	private UserPasswordResetLogService userPasswordResetLogService;
	
	@Resource
	private OrganizationUserRelationshipDao organizationUserRelationshipDao;
	
	@Override
	public Page<User> query(User t,Page page){
		   Object[] queryCondiction=createQueryCondiction(t);
		   StringBuffer jpql=(StringBuffer)queryCondiction[0];
	       @SuppressWarnings("unchecked")
		   List<Object> params=(List<Object>)queryCondiction[1];
           return userDao.query("select count(t.id) "+jpql.toString(), jpql.toString(), page, params.toArray());
	
	}
	
	
	
	@Override
	public String queryToJsonStr(User t,Page page) {
		Page<User> result=query(t, page);
		BootstrapGrid grid=new BootstrapGrid(result);
		return grid.toString();
	}

	
	@Override
	public BaseResponse idoUpdate(User t) {
		
		BaseResponse res=new BaseResponse();
		if(StringUtils.isEmpty(t.getName())){
			res.setStatus(0);
			res.setMessage("操作失败，用户名不能为空！");
			return res;
		}
		if(!StringUtils.isEmpty(t.getMobilePhone())&&!ValidateUtils.isMobileNO(t.getMobilePhone())){
			res.setStatus(0);
			res.setMessage("操作失败，手机号格式不正确！");
			return res;
		}
		
		if(!StringUtils.isEmpty(t.getEmail())&&!ValidateUtils.isEmail(t.getEmail())){
		    	res.setStatus(0);
				res.setMessage("操作失败，邮箱格试不正确！");
				return res;
		}
		
		User ut=userDao.findById(User.class, t.getId(),LockModeType.PESSIMISTIC_WRITE);
		ut.setRealName(t.getRealName());
		ut.setEmail(t.getEmail());
		ut.setMobilePhone(t.getMobilePhone());
		ut.setGender(t.getGender());
		ut.setAccountNonLocked(t.getAccountNonLocked());
		ut.setDepartment(t.getDepartment());
		
		if(ut.getAccountNonExpired()==false&&t.getAccountNonExpired()==true){
			ut.setAccountNonExpired(t.getAccountNonExpired());
			Date accountExpiredTime=DateUtils.getDateAfter(new Date(),90);
			ut.setAccountExpiredTime(accountExpiredTime);
		}
	
		if(StringUtils.isEmpty(t.getWechatId())){
			 ut.setWechatId(null);
		}else{
		     ut.setWechatId(t.getWechatId());
		}
		if(!StringUtils.isEmpty(t.getPassword())){
		  try {
			  ut.setPassword(EncryptUtils.encryptSHA(t.getPassword()));
		  } catch (Exception e) {
			  e.printStackTrace();
			  res.setStatus(0);
			  res.setMessage("操作失败，"+e.getMessage());
			  return res;
		  }
		}
	
		
		userRoleService.doDeleteUserRoleByRoleIds(ut, t.getDeleteRoleIds());
		userRoleService.doAddUserRoleByRoleIds(ut, t.getRoleIds());
		organizationUserRelationshipDao.save(ut, t.getOrganizationIds(), t.getDeleteOrganizationIds());
	   
		userDao.saveOrUpdate(ut);
	    res.setStatus(1);
		res.setMessage("操作成功！");
		return res;
	}

	
	

	@Override
	public BaseResponse idoAdd(User t) {
		BaseResponse res=new BaseResponse();
		if(StringUtils.isEmpty(t.getName())){
			res.setStatus(0);
			res.setMessage("操作失败，用户名不能为空！");
			return res;
		}
		
		if(userDao.findByName(t.getName())!=null){
			res.setStatus(0);
			res.setMessage("操作失败，用户名已存在！");
			return res;
	    }
		
		if(userDao.findWechatId(t.getWechatId())!=null){
			res.setStatus(0);
			res.setMessage("操作失败，wechatId已存在！");
			return res;
	    }
		if(!StringUtils.isEmpty(t.getMobilePhone())&&!ValidateUtils.isMobileNO(t.getMobilePhone())){
			res.setStatus(0);
			res.setMessage("操作失败，手机号格式不正确！");
			return res;
		}
		
		if(!StringUtils.isEmpty(t.getEmail())&&!ValidateUtils.isEmail(t.getEmail())){
		    	res.setStatus(0);
				res.setMessage("操作失败，邮箱格试不正确！");
				return res;
		}
		
		if("".equals(t.getWechatId())){
			t.setWechatId(null);
		}
		
		if(t.getGender()==null){
			t.setGender(Gender.UNKNOWN);
		}
		t.setAccountNonExpired(true);
		t.setAccountNonLocked(true);
		t.setEnable(true);
		t.setCredentialsNonExpired(true);
		t.setCreateTime(new Date());
		t.setUpdateTime(t.getCreateTime());
		try {
			t.setPassword(EncryptUtils.encryptSHA(t.getPassword()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		userDao.persist(t);
		
		organizationUserRelationshipDao.save(t, t.getOrganizationIds(), t.getDeleteOrganizationIds());
		userRoleService.doAddUserRoleByRoleIds(t, t.getRoleIds());
		
		res.setStatus(1);
		res.setMessage("操作成功！");
		return res;
	}
	@Override
	public long idoAddByWechat(String wechatId){
		return idoAddByWechat(wechatId, "普通用户", "", "");
	}
	
	@Override
	public long idoAddByWechat(String wechatId,String roleName){
		return idoAddByWechat(wechatId, roleName,"", "");
	}
	@Override
	public long idoAddByWechat(String wechatId,String roleName,String realName,String mobilePhoneNo){
		if(!StringUtils.isEmpty(mobilePhoneNo)&&!ValidateUtils.isMobileNO(mobilePhoneNo)){
			  return 0L;
		}
		User t=new User();
		if(userDao.findWechatId(wechatId)!=null){
			   return 1L;
		}
		t.setName(wechatId);
		t.setPassword(wechatId);
		t.setWechatId(wechatId);
		t.setRealName(realName);
		List<Role> list=roleService.findAll("from Role where nameZh=?1",roleName);
		if(list.size()==0){
			return 2L;
		}
		Role role=list.get(0);
		t.setRoleIds(String.valueOf(role.getId()));
		doAdd(t);
		return 3L;
	}
	
	

	
	private long doAdd(User t) {
		if(t.getGender()==null){
			t.setGender(Gender.UNKNOWN);
		}
		t.setAccountNonExpired(true);
		t.setAccountNonLocked(true);
		t.setEnable(true);
		t.setCredentialsNonExpired(true);
		t.setCreateTime(new Date());
		t.setUpdateTime(t.getCreateTime());
		try {
			t.setPassword(EncryptUtils.encryptSHA(t.getPassword()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		userDao.persist(t);
		//userRoleService.setUserRoleByRoleIds(t.getRoleIds(),t);
		
		userRoleService.doAddUserRoleByRoleIds(t, t.getRoleIds());
		return 1L;
	}
	@Override
	public BaseResponse idoUpdatePassword(String username,String orinPassword,String newPassword){
		User u=findByName(username);
		return doUpdatePassword(orinPassword, newPassword, u);
	}
	
	@Override
	public BaseResponse idoUpdatePassword(String orinPassword,String newPassword){
		User u=getCurrentUser();
		return doUpdatePassword(orinPassword, newPassword, u);
	}


	private BaseResponse doUpdatePassword(String orinPassword, String newPassword, User u) {
		BaseResponse res=new BaseResponse();
		if(u==null){
			res.setStatus(0);
			res.setMessage("操作失败，用户不存在！");
			return res;
		}
		if(StringUtils.isEmpty(orinPassword)){
			res.setStatus(0);
			res.setMessage("操作失败，原密码不能为空！");
			return res;
		}
		if(StringUtils.isEmpty(newPassword)){
			res.setStatus(0);
			res.setMessage("操作失败，新密码不能为空！");
			return res;
		}
		try {
			orinPassword=EncryptUtils.encryptSHA(orinPassword);
			newPassword=EncryptUtils.encryptSHA(newPassword);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		if(!orinPassword.equals(u.getPassword())){
			res.setStatus(0);
			res.setMessage("操作失败，原密码不正确！");
			return res;
		}
		u.setPassword(newPassword);
		Date expiredTime=DateUtils.getDateAfter(new Date(),90);
		u.setCredentialsExpiredTime(expiredTime);
		userDao.saveOrUpdate(u);
		res.setStatus(1);
		res.setMessage("操作成功！");
		return res;
	}
	
	@Override
	public User getCurrentUser(){
		if(SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserDetails){
			UserDetails userDetails=(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			String userName=userDetails.getUsername();
			User user = userDao.findByName(userName);
			return user;
		}
		return null;
	}
	@Override
	public String getCurrentUserName(){
		UserDetails userDetails=(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	   return userDetails.getUsername();
	}


	@Override
	public BaseResponse idoUpdateUserInfo(User t) {
		
		BaseResponse res=new BaseResponse();
		User user=getCurrentUser();
		user.setAddress(t.getAddress());
		user.setCompany(t.getCompany());
		user.setEmail(t.getEmail());
		user.setGender(t.getGender());
		user.setRealName(t.getRealName());
		user.setPhone(t.getPhone());
		user.setMobilePhone(t.getMobilePhone());
		user.setPhoto(t.getPhoto());
		userDao.saveOrUpdate(user);
		res.setStatus(1);
		res.setMessage("操作成功！");
		return res;
	}
	
	
	
	public List<User>queryByLikeName(String name){
		String userName=getCurrentUserName();
		if(StringUtils.isEmpty(name)){
			return userDao.findAll("from User t where t.name!=?1",userName);
		}
		return userDao.findAll("from User t where t.name like ?1 and t.name!=?2",name+"%",userName);
	}
	
	public List<User>queryByName(String name){
		return userDao.findAll("from User t where t.name＝?1",name);
	}
	
	

	

	public List<User> queryAllByDepartmentId(Long departmentId){
		return userDao.findAll("from User where department.id=?1",departmentId);
	}
	@Override
	public User queryById(Long id){
		return userDao.findById(User.class, id);
	}
	@Override
	public User findByName(String username) {
		return userDao.findByName(username);
	}
	@Override
	public User findWechatId(String wechatId) {
		return userDao.findWechatId(wechatId);
	}
	
	public long idoAddPotentialCustomerUser(String mobilePhoneNo){
		return doAdd(mobilePhoneNo,"潜客用户");
	}
	public long idoAddCarOwnerUser(String mobilePhoneNo){
		return doAdd(mobilePhoneNo,"车主用户");
	}
	private long doAdd(String mobilePhoneNo,String roleName) {
		User t=new User();
		if(userDao.findByName(mobilePhoneNo)!=null){
			   return 0L;
		}
		t.setName(mobilePhoneNo);
		t.setPassword(mobilePhoneNo);
		List<Role> list=roleService.findAll("from Role where nameZh=?1",roleName);
		if(list.size()==0){
			return 3L;
		}
		Role role=list.get(0);
		t.setRoleIds(String.valueOf(role.getId()));
		return doAdd(t);
	}
	
	@Override
	public long idoAddByQyWechat(String wechatId,String realName,String mobilePhone,String gender,String photo,String roleName,String departmentCode){
		User t=new User();
		if(userDao.findWechatId(wechatId)!=null){
			   return 0L;
		}
		t.setRealName(realName);
		t.setMobilePhone(mobilePhone);
		if("1".equals(gender)){
			t.setGender(Gender.M);
		}else if("0".equals(gender)){
			t.setGender(Gender.FM);
		}else{
			t.setGender(Gender.UNKNOWN);
		}
		Department department=departmentService.findByCode(departmentCode);
		t.setDepartment(department);
	    t.setPhoto(photo);
		t.setName(wechatId);
		t.setPassword(wechatId);
		t.setWechatId(wechatId);
		List<Role> list=roleService.findAll("from Role where nameZh=?1",roleName.trim());
		log.info("查找到的角色列表大小"+list.size());
		if(list.size()==0){
			return 3L;
		}
		Role role=list.get(0);
		log.info("查找到的角色名称"+role.getNameZh());
		t.setRoleIds(String.valueOf(role.getId()));
		long retVal=doAdd(t);
		userDao.saveOrUpdate(t);//主方法在spring security中调用所以并不支持事务需要手动更新
		return retVal;
	}
	@Override
	public long idoAddByUserApplication(String userName,String realName,String mobilePhone,String gender,String photo,String roleName,String departmentCode,String email,String password){
		User t=new User();
		if(userDao.findWechatId(userName)!=null){
			   return 0L;
		}
		t.setRealName(realName);
		t.setMobilePhone(mobilePhone);
		if("1".equals(gender)){
			t.setGender(Gender.M);
		}else if("0".equals(gender)){
			t.setGender(Gender.FM);
		}else{
			t.setGender(Gender.UNKNOWN);
		}
		Department department=departmentService.findByCode(departmentCode);
		if(department==null){
			List<Department> departmentList=departmentService.findAllByLikeName(departmentCode);
			if(departmentList.size()>0){
				department=departmentList.get(0);
			}
		}
		t.setDepartment(department);
	    t.setPhoto(photo);
		t.setName(userName);
		t.setPassword(password);
		t.setWechatId(userName);
		t.setEmail(email);
		Date expiredTime=DateUtils.getDateAfter(new Date(),90);
		t.setAccountExpiredTime(expiredTime);
		t.setCredentialsExpiredTime(expiredTime);
		List<Role> list=roleService.findAll("from Role where nameZh=?1",roleName.trim());
		log.info("查找到的角色列表大小"+list.size());
		if(list.size()==0){
			return 3L;
		}
		Role role=list.get(0);
		log.info("查找到的角色名称"+role.getNameZh());
		t.setRoleIds(String.valueOf(role.getId()));
		long retVal=doAdd(t);
		userDao.saveOrUpdate(t);//主方法在spring security中调用所以并不支持事务需要手动更新
		return retVal;
	}

	@Override
	public User findById(Long id){
		return userDao.findById(User.class, id);
	}
	@Override
	public BaseResponse idoDelete(long id){
		BaseResponse res=new BaseResponse();
		User t=findById(id);
		if(t==null){
			res.setStatus(0);
			res.setMessage("操作失败，用户不存在！");
			return res;
		}
		t.setDeleted(true);
		t.setDeletedTime(new Date());
		t.setName(t.getName().concat("_deleted_").concat(DateUtils.format(new Date(), DateUtils.FORMAT_DATE_TIME_YYYYMMDDHHMMSS)));
		if(!StringUtils.isEmpty(t.getWechatId())){
			t.setWechatId(t.getWechatId().concat("_deleted_").concat(DateUtils.format(new Date(), DateUtils.FORMAT_DATE_TIME_YYYYMMDDHHMMSS)));
		}
		userDao.saveOrUpdate(t);
		res.setStatus(1);
		res.setMessage("操作成功！");
		return res;
	}
	@Override
	public void idoUpdateAllAttr(User t){
        userDao.saveOrUpdate(t);
    }
	@Override
	public BaseResponse idoResetPassword(String userName,String email){
		BaseResponse res=new BaseResponse();
		List<User> userList=userDao.findAll("from User t where t.name=?1 and t.email=?2", userName,email);
		
		if(userList.size()==0){
			res.setStatus(0);
			res.setMessage("操作失败，用户名或邮箱不存在！");
			return res;
		}
		User user=userDao.findById(User.class, userList.get(0).getId(), LockModeType.PESSIMISTIC_WRITE);
		String resetPassword=ExtendedStringUtils.getRandomString(8);
		String encriptPassword="";
		try {
			encriptPassword=EncryptUtils.encryptSHA(resetPassword);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		user.setPassword(encriptPassword);
		user.setCredentialsExpiredTime(new Date());
		userDao.saveOrUpdate(user);
		userPasswordResetLogService.doAdd(user, resetPassword);
		res.setStatus(1);
		res.setMessage("操作成功！新的密码稍后自动发到您输入的邮箱，请登录系统后修改密码！");
		return res;
	}
	
	public List<User>queryAll(User t){
		   Object[] qc=createQueryCondiction(t);
		   StringBuffer jpql=(StringBuffer)qc[0];
	       @SuppressWarnings("unchecked")
		   List<Object> params=(List<Object>)qc[1];
		   return userDao.findAll(jpql.toString(), params.toArray());
	}
	
	private Object[] createQueryCondiction(User t) {
		
		   StringBuffer jpql=new StringBuffer("from User t where 1=1");
			
			List<Object> params=new ArrayList<Object>();
			String minTime=" 00:00:00";
	        String maxTime=" 23:59:59";
			if(StringUtils.isNotEmpty(t.getName())){
				params.add(t.getName()+"%");
				jpql.append(" and t.name like?"+params.size());
			}
			
			if(StringUtils.isNotEmpty(t.getEmail())){
				params.add(t.getEmail());
				jpql.append(" and t.email=?"+params.size());
			}
			if(StringUtils.isNotEmpty(t.getMobilePhone())){
				params.add(t.getMobilePhone());
				jpql.append(" and t.mobilePhone=?"+params.size());
			}
			if(StringUtils.isNotEmpty(t.getRealName())){
				params.add(t.getRealName());
				jpql.append(" and t.realName=?"+params.size());
			}
			
			if(t.getAccountNonLocked()!=null){
				params.add(t.getAccountNonLocked());
				jpql.append(" and t.accountNonLocked=?"+params.size());
			}
			if(t.getEnable()!=null){
				params.add(t.getEnable());
				jpql.append(" and t.enable=?"+params.size());
			}
			
		   if(StringUtils.isNotEmpty(t.getTimeMin())){
				params.add(DateUtils.parseDate(t.getTimeMin()+minTime, DateUtils.FORMAT_DATE_TIME_DEFAULT));
				jpql.append(" and t.createTime>=?"+(params.size()));
		   }
		   if(StringUtils.isNotEmpty(t.getTimeMax())){
		    	params.add(DateUtils.parseDate(t.getTimeMax()+maxTime, DateUtils.FORMAT_DATE_TIME_DEFAULT));
				jpql.append(" and t.createTime<=?"+(params.size()));
		   }
		
			params.add(Boolean.FALSE);
			
			jpql.append(" and t.deleted=?"+params.size());
			
			if(!StringUtils.isEmpty(t.getRoles())){
				params.add(t.getRoles());
				jpql.append(" and t.id in(select user.id from UserRole where role.nameZh=?"+params.size()+")");
			}
	        if(!StringUtils.isEmpty(t.getOrganizationNames())){
	        	params.add(t.getOrganizationNames());
				jpql.append(" and t.id in(select user.id from OrganizationUserRelationship where organization.name=?"+params.size()+")");
			}
		
	        return new Object[]{jpql,params};
	}



	public HSSFWorkbook createExcel(User t){
		List<User> userList=queryAll(t);
		HSSFWorkbook wb = new HSSFWorkbook(); // create new workbook object
		List<Object[]> objectArrayList=createObjectArrayList(userList);
		return ExcelUtils.createExcelSheet(wb, objectArrayList, "sheet0", new String[]{"用户名","姓名","电子邮箱","联系电话","角色","所属机构"});
	}
	private List<Object[]> createObjectArrayList(List<User> userList){
		List<Object[]> objectArrayList=new ArrayList<Object[]>();
		for(User t:userList){
			objectArrayList.add(new Object[]{t.getName(),t.getRealName(),t.getEmail(),t.getPhone(),t.getRoles(),t.getOrganizationNames()});
		}
		return objectArrayList;
	}


}
